<?php

namespace App\Services;

use App\Common\Libs\ArrayHelper;
use App\Common\Libs\Dispatch\Queue;
use App\Common\Libs\IdBuilder;
use App\Consts\ExceptionCode;
use App\Consts\GlobalConst;
use App\Consts\GlobalCounterConst;
use App\Consts\GlobalPackageConst;
use App\Consts\GlobalQueueConst;
use App\Events\CacheCounterEvent;
use App\Events\CollectPackage\CreateCollectPackageEvent;
use App\Events\CollectPackage\DelCollectPackageEvent;
use App\Exceptions\Error;
use App\Formats\CollectFormat;
use App\Jobs\Controller\PackageJob;
use App\Models\Cache\CacheKey;
use App\Models\UserCollectPackage;
use Illuminate\Support\Facades\DB;

/**
 * @package App\Services
 * @see PackageService
 */
class PackageService extends BaseService
{

    private $_repository;
    private $_collectPackage;

    public function __construct()
    {
        parent::__construct();
        $this->_repository = repository()->PackageRepository;
    }

    /**
     * 收藏主体时，获取收藏夹列表
     * @param $searchParams
     * @return array
     */
    public function getCollectPackageListByTargetId($searchParams)
    {
        if (!empty($searchParams['last_id'])) {
            $collectPackage = $this->_repository->getCollectPackageById($searchParams['last_id']);
            if ($collectPackage) {
                $searchParams['last_updated_at'] = $collectPackage->updated_at;
            }
        }

        $dataProvider = $this->_repository->getUserCollectPackageList($searchParams);
        $pagination = $this->getPagination();
        $collectPackageList = $dataProvider->getModels();

        $list = [];
        /**
         * @var UserCollectPackage $collectPackage
         */
        foreach ($collectPackageList as $collectPackage) {
            $list[] = $collectPackage->commonFormat();
        }

        // 新用户列表为空，需要为其添加[sys_default_package]表中的数据
        if (empty($list)) {
            return $this->createDefaultCollectPackage($searchParams['current_user_id']);
        }

        return self::outputMoreList($dataProvider, $pagination, $list);
    }

    public function getCollectPackageTargetList($searchParams)
    {
        $dataProvider = $this->_repository->getCollectPackageTargetList($searchParams);
        $pagination = $this->getPagination();
        $collects = $dataProvider->getModels();

        $list = formats()->CollectFormat->formatCollectList($collects, $searchParams['current_user_id'], CollectFormat::PACKAGE_TARGET_LIST);

        return self::outputMoreList($dataProvider, $pagination, $list);
    }

    /**
     * 获取用户收藏夹列表
     * @param $searchParams
     * @return array
     */
    public function getUserCollectPackageList($searchParams)
    {
        // 被查看用户ID == 当前登录用户：可以看见公开和私有的收藏夹
        if (!array_key_exists('is_public', $searchParams)) {
            if ($searchParams['user_id'] === $searchParams['current_user_id']) {
                $searchParams['is_public'] = [GlobalPackageConst::IS_NOT_PUBLIC, GlobalPackageConst::IS_PUBLIC];
            } else {
                $searchParams['is_public'] = [GlobalPackageConst::IS_PUBLIC];
            }
        }

        $dataProvider = $this->_repository->getUserCollectPackageList($searchParams);
        $pageSize = $searchParams['page_size'] ?? GlobalConst::BASE_PAGE_COUNT;
        $pagination = $this->getPagination(['page_size' => $pageSize]);
        $collectPackageList = $dataProvider->getModels();

        $list = [];
        /**
         * @var UserCollectPackage $collectPackage
         */
        foreach ($collectPackageList as $collectPackage) {
            $list[] = $collectPackage->commonFormat();
        }

        // 新用户列表为空，需要为其添加[sys_default_package]表中的数据
        if (empty($list) && $searchParams['current_user_id'] && empty($searchParams['not_create_default'])) {
            return $this->createDefaultCollectPackage($searchParams['current_user_id']);
        }

        return self::outputMoreList($dataProvider, $pagination, $list);
    }

    /**
     * 新增收藏夹
     * @param $loadData
     * @return bool|\Illuminate\Http\JsonResponse|array
     */
    public function createCollectPackage($loadData)
    {
        // 验证收藏夹是否存在
        $collectPackage = $this->_repository->getCollectPackageByName($loadData['user_id'], $loadData['name']);
        if ($collectPackage && $collectPackage->is_deleted == GlobalConst::IS_NOT_DELETE) {
            return Error::handle(lang('Collect package is exits'));
        }

        $collectPackageId = IdBuilder::getUniqueID();
        $loadData = ArrayHelper::merge($loadData, [
            'collect_package_id' => $collectPackageId,
            'total' => 0,
        ]);

        DB::beginTransaction();
        try {
            // 新增收藏夹
            $collectPackage = $this->_repository->createCollectPackage($loadData);
            if (!$collectPackage) {
                return Error::handle(lang('Collect package is exits'));
            }

            // 【暂时】新增索引记录
            $this->_repository->createIndexCollectPackage([
                'collect_package_id' => $collectPackageId,
                'user_id' => $loadData['user_id'],
                'collect_package_name' => $loadData['name'],
                'is_public' => $loadData['is_public']
            ]);

            // 同步更新用户收藏夹数
            $this->syncCounterFromCache($loadData['user_id']);

            /**
             * 队列做以下几件事：
             *  1. 记录日志
             */
            CreateCollectPackageEvent::dispatch($collectPackage);

            DB::commit();

            return $collectPackage->commonFormat();
        } catch (\Exception $e) {
            DB::rollBack();
            return Error::handle(lang('Unstable network'));
        }
    }

    public function delCollectPackage($userId, $packageId)
    {
        $collectPackage = $this->_repository->getCollectPackageById($packageId);
        if (!$collectPackage) {
            return Error::handle();
        }

        // 收藏夹不是本人
        if ($collectPackage->user_id != $userId) {
            return Error::handle(lang('Insufficient permissions'), ExceptionCode::INSUFFICIENT_PERMISSIONS);
        }

        // 默认收藏夹不可删除
        if ($collectPackage->is_default == GlobalPackageConst::IS_DEFAULT) {
            return Error::handle(lang('This collect package is default'));
        }
        DB::beginTransaction();
        try {
            // 删除收藏夹
            $this->_repository->delCollectPackageBySelf($collectPackage);

            // 同步更新用户收藏夹数
            $this->syncCounterFromCache($collectPackage->user_id, GlobalCounterConst::DECREASE);

            /**
             * 队列做以下几件事：
             *  1. 更新收藏内容的收藏数 -1，记录取消收藏日志
             *  2. 记录日志
             *  3. 取消所有内容的收藏态【等于取消收藏的一切操作】
             */
            DelCollectPackageEvent::dispatch($collectPackage);

            DB::commit();

            return $collectPackage->commonFormat();
        } catch (\Exception $e) {
            DB::rollBack();
            return Error::handle($e->getMessage());
        }
    }

    public function updateCollectPackage($loadData)
    {
        // 获取收藏夹
        $collectPackage = $this->_repository->getCollectPackageById($loadData['package_id']);
        if (!$collectPackage) {
            return Error::handle();
        }

        // 收藏夹不是本人
        if ($collectPackage->user_id != $loadData['user_id']) {
            return Error::handle(lang('Insufficient permissions'), ExceptionCode::INSUFFICIENT_PERMISSIONS);
        }

        // 默认收藏夹不可删除
        if ($collectPackage->is_default == GlobalPackageConst::IS_DEFAULT) {
            return Error::handle(lang('This collect package is default'));
        }

        // 验证收藏夹是否存在
        $judgeRes = $this->_repository->judgeCollectPackageExistByName($loadData['user_id'], $loadData['package_id'], $loadData['name']);
        if ($judgeRes) {
            return Error::handle(lang('Collect package is exits'));
        }

        DB::beginTransaction();
        try {
            // 修改收藏夹
            $this->_repository->updateCollectPackage($collectPackage, [
                'name' => $loadData['name'] ?? $collectPackage->name,
                'description' => $loadData['description'] ?? $collectPackage->description,
                'is_public' => $loadData['is_public'] ?? $collectPackage->is_public,
            ]);

            // 修改收藏夹
            $this->_repository->updateIndexCollectPackage($collectPackage, [
                'collect_package_name' => $loadData['name'] ?? $collectPackage->name,
                'is_public' => $loadData['is_public'] ?? $collectPackage->is_public,
            ]);

            DB::commit();

            return true;
        } catch (\Exception $e) {
            DB::rollBack();
            return Error::handle(lang('Unstable network'));
        }
    }

    /**
     * 新增/删除收藏夹后，更新用户计数
     * @param $userId
     * @param int $trend
     */
    public function syncCounterFromCache($userId, $trend = GlobalCounterConst::INCREASE)
    {
        CacheCounterEvent::dispatch([
            'key_params' => ['user_id' => $userId],
            'cache_key' => CacheKey::COUNTER_USER,
            'values' => GlobalCounterConst::COUNT_COLLECT_PACKAGE,
            'trend' => $trend
        ]);
    }

    /**
     * 通过ID获取收藏夹
     * @param $collectPackageId
     * @return UserCollectPackage|false|mixed
     */
    public function getCollectPackageById($collectPackageId)
    {
        if (empty($this->_collectPackage[$collectPackageId])) {
            $collectPackage = $this->_repository->getCollectPackageById($collectPackageId);
            if (!$collectPackage) {
                return false;
            }
            $this->_collectPackage[$collectPackageId] = $collectPackage;
        }

        return $this->_collectPackage[$collectPackageId];
    }

    /**
     * 修改收藏夹的内容总数
     * @param array $data ['user_id' => '', 'package_id' => '', 'trend' => '']
     * @return \Illuminate\Foundation\Bus\PendingDispatch
     */
    public function changeTotal($data)
    {
        return Queue::getInstance(PackageJob::class)
            ->push($data, GlobalQueueConst::PACKAGE_CHANGE_TOTAL);
    }

    /**
     * 新用户没有任何收藏夹，此时创建系统收藏夹
     * @param $userId
     * @return array
     */
    private function createDefaultCollectPackage($userId)
    {
        if (empty($userId)) {
            return [
                'have_more' => false,
                'list' => []
            ];
        }
        // 获取系统收藏夹
        $defaultCollectPackages = $this->_repository->getDefaultCollectPackage();

        $list = [];
        foreach ($defaultCollectPackages as $defaultCollectPackage) {
            $collectPackage = $this->_repository->createCollectPackage([
                'collect_package_id' => IdBuilder::getUniqueID(),
                'user_id' => $userId,
                'name' => $defaultCollectPackage->name,
                'description' => $defaultCollectPackage->description,
                'total' => 0,
                'is_deleted' => GlobalConst::IS_NOT_DELETE,
                'is_public' => $defaultCollectPackage->is_public,
                'is_default' => GlobalPackageConst::IS_DEFAULT,
                'is_top' => $defaultCollectPackage->is_top,
            ]);
            if ($defaultCollectPackage) {
                // 【暂时】新增索引记录
                $this->_repository->createIndexCollectPackage([
                    'collect_package_id' => $collectPackage->collect_package_id,
                    'user_id' => $collectPackage->user_id,
                    'collect_package_name' => $collectPackage->name,
                    'is_public' => $defaultCollectPackage->is_public,
                ]);
                $list[] = $collectPackage->commonFormat();
            }

            // 防止毫秒级ID重复
            sleep(0.05);
        }

        return [
            'have_more' => false,
            'list' => $list
        ];
    }
}
